using EventHub.Users;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Users;

namespace EventHub.Organizations.Memberships {
    public class OrganizationMembershipAppService(
        OrganizationMembershipManager organizationMembershipManager,
        IUserRepository userRepository,
        IRepository<Organization, Guid> organizationRepository,
        IOrganizationMembershipRepository organizationMembershipsRepository) : EventHubAppService, IOrganizationMembershipAppService {
        [Authorize]
        public async Task JoinAsync(Guid organizationId) {
            await organizationMembershipManager.JoinAsync(
                await organizationRepository.GetAsync(organizationId),
                await userRepository.GetAsync(CurrentUser.GetId())
            );
        }

        [Authorize]
        public async Task LeaveAsync(Guid organizationId) {
            await organizationMembershipsRepository.DeleteAsync(
                x => x.OrganizationId == organizationId && x.UserId == CurrentUser.GetId()
            );
        }

        [Authorize]
        public async Task<bool> IsJoinedAsync(Guid organizationId) {
            return await organizationMembershipManager.IsJoinedAsync(
                await organizationRepository.GetAsync(organizationId),
                await userRepository.GetAsync(CurrentUser.GetId())
            );
        }

        public async Task<PagedResultDto<OrganizationMemberDto>> GetMembersAsync(OrganizationMemberListFilterDto input) {
            var organizationMembershipsQueryable = await organizationMembershipsRepository.GetQueryableAsync();
            var userQueryable = await userRepository.GetQueryableAsync();

            var query = from organizationMembership in organizationMembershipsQueryable
                        join user in userQueryable on organizationMembership.UserId equals user.Id
                        where organizationMembership.OrganizationId == input.OrganizationId
                        orderby organizationMembership.CreationTime descending
                        select user;

            var totalCount = await AsyncExecuter.CountAsync(query);

            var users = await AsyncExecuter.ToListAsync(query.PageBy(input));

            return new PagedResultDto<OrganizationMemberDto>(
                totalCount,
                ObjectMapper.Map<List<IdentityUser>, List<OrganizationMemberDto>>(users)
            );
        }
    }
}